package msghandler

import (
	"fmt"
	"reflect"
	"src/zeus/common"
	"src/zeus/iserver"
	"src/zeus/msgdef"
	"src/zeus/safecontainer"
	"src/zeus/serializer"
	"strings"
	"sync"

	"src/zeus/logger"

	"github.com/spf13/viper"
)

/*
	MsgHandler 作为底层通讯层与上层应用层之间逻辑传递的桥梁
*/

// IMsgHand 消息处理模块的接口
type IMsgHand interface {
	//处理消息
	DoMsg()
	//处理Msg消息
	DoNormalMsg(string, interface{}) error
	//处理RPC消息
	DoRPCMsg(string, []byte) error
	// FireMsg 触发消息, 保证不被挂起
	FireMsg(name string, content interface{})
	// FireRPC 触发消息, 保证不被挂起
	FireRPC(methodName string, data []byte)

	// RegMsgProc 注册消息处理对象
	// 其中 proc 是一个对象，包含是类似于 MsgProc_XXXXX的一系列函数，分别用来处理不同的消息
	RegMsgProc(proc interface{})
	//注册出错时的处理函数
	RegOnPanicFunc(func(err error))
	//调用出错处理函数
	OnPanicFunc(err error)
	//获取有消息时的chan
	GetCallChan() chan bool
	// SetMainHander 设置父级消息路由器
	SetMainHander(msghandler iserver.IMsgHandler)

	SetEnable(enable bool)

	getMsgList() *safecontainer.SafeListT[*msgFireInfo]
	getRpcList() *safecontainer.SafeListT[*rpcFireInfo]
	fireMsg(msg *msgFireInfo)
	fireRPC(msg *rpcFireInfo)
}

const (
	msgType_MSG uint8 = 1
	msgType_RPC uint8 = 2
)

// NewMsgHandler 创建一个新的消息处理器
func NewMsgHandler() *MsgHandler {

	return &MsgHandler{

		enable: true,
		//msgCount:     make(map[string][]int64),
		msgFireInfo:  safecontainer.NewSafeListT[*msgFireInfo](),
		rpcFireInfo:  safecontainer.NewSafeListT[*rpcFireInfo](),
		defaultFuncs: make([]reflect.Value, 0, 10),
		msgChan:      make(chan bool, 1),
	}
}

type IMsgInfo interface {
	GetHandler() *MsgHandler
}

// msgFireInfo 触发一个事件时必须的信息
type msgFireInfo struct {
	handler *MsgHandler
	name    string
	content interface{}
}

func (msg *msgFireInfo) GetHandler() *MsgHandler {
	return msg.handler
}

type rpcFireInfo struct {
	handler    *MsgHandler
	methodName string
	data       []byte
}

func (rpc *rpcFireInfo) GetHandler() *MsgHandler {
	return rpc.handler
}

// MsgHandler 消息处理中心
type MsgHandler struct {
	//TODO moved to global msgCmd. TODO fixme
	msgFuncs sync.Map //MsgProc_前缀 的所有方法
	rpcFuncs sync.Map //RPC_前缀     的所有方法
	srvFuncs sync.Map //Srv_前缀     的服务器之间的调用需要回复

	enable       bool
	defaultFuncs []reflect.Value

	msgFireInfo *safecontainer.SafeListT[*msgFireInfo] //MsgProc_ 消息
	rpcFireInfo *safecontainer.SafeListT[*rpcFireInfo] //RPC_ 消息
	onPanicFunc func(error)

	msgChan chan bool
	/*
		parent 如果多个msghandlers 共用一个协程的时候，会有一个主MsgHandlers
		这样的话，就可以把所有消息放到这个主MsgHandlers里
	*/
	mainHander             IMsgHand
	ProcessCommonErrorFunc func(msg msgdef.IMsg, err error)
}

// 获取子处理器
func (this *MsgHandler) ClearSafeList() {
	for !this.msgFireInfo.IsEmpty() {
		p, err := this.msgFireInfo.Pop()
		logger.Info("msgFireInfo:", p, err)
	}
	for !this.rpcFireInfo.IsEmpty() {
		p, err := this.rpcFireInfo.Pop()
		logger.Info("rpcFireInfo:", p, err)
	}

	this.msgFireInfo = safecontainer.NewSafeListT[*msgFireInfo]()
	this.rpcFireInfo = safecontainer.NewSafeListT[*rpcFireInfo]()
}
func (this *MsgHandler) GetNewSubHandler() (result *MsgHandler) {
	result = NewMsgHandler()
	result.SetMainHander(this)
	return result
}

// SetEnable 临时方法
func (handlers *MsgHandler) SetEnable(enable bool) {
	handlers.enable = enable
}

func (handlers *MsgHandler) RegOnPanicFunc(f func(err error)) {
	handlers.onPanicFunc = f
}

func (handlers *MsgHandler) OnPanicFunc(err error) {
	if handlers.onPanicFunc != nil {
		handlers.onPanicFunc(err)
	}
}

func (handlers *MsgHandler) getMsgList() *safecontainer.SafeListT[*msgFireInfo] {
	return handlers.msgFireInfo
}
func (handlers *MsgHandler) getRpcList() *safecontainer.SafeListT[*rpcFireInfo] {
	return handlers.rpcFireInfo
}

// RegMsgProc 注册消息处理对象
// 其中 proc 是一个对象，包含是类似于 MsgProc_XXXXX的一系列函数，分别用来处理不同的消息
func (handlers *MsgHandler) RegMsgProc(proc interface{}) {

	v := reflect.ValueOf(proc)
	t := reflect.TypeOf(proc)

	for i := 0; i < t.NumMethod(); i++ {
		methodName := t.Method(i).Name

		ifWarnAnonymousFunc := func() {
			if !logger.CheckKey(logger.LogKey_RegMsgProc) {
				return
			}
			// 获取方法的接收器类型
			recvType := t.Method(i).Type.In(0)
			// 检查接收器类型是否与Outer相同
			// TODO: 目前不太容易判断 当前方法 是否是匿名结构体里面的方法, 只能通过 方法名称对比是否在匿名结构体里面的方法 来判断,折磨.
			if recvType != t {
				logger.Error("注册MsgProc 使用匿名组合是很危险的,请自行判断 ", recvType.String(), t.String())
			}
			logger.Debug(logger.LogKey_RegMsgProc, methodName, ":", t.Method(i).Type.NumIn(), t.Method(i).Type.Name(),
				" 注册MsgProc的方法的接收第一个参数是 ", recvType.String(), " , 本结构体为:", t.String(),
			) //" Method.PkgPath=(", t.Method(i).PkgPath, ",", t.Method(i).Type.String(), ")", v.Method(i).String())
		}
		//MsgProc前缀的所有方法
		msgName, msgHandler, err := handlers.getMsgHandler(methodName, v.MethodByName(methodName))
		if err == nil {
			ifWarnAnonymousFunc()
			handlers.addMsgHandler(msgName, msgHandler)
			continue
		}

		// 判断是否是RPC处理函数
		msgName, msgHandler, err = handlers.getRPCHandler(methodName, v.MethodByName(methodName))
		if err == nil {
			ifWarnAnonymousFunc()
			handlers.addRPCHandler(msgName, msgHandler)
		}
		// 判断是否是Srv处理函数
		msgName, msgHandler, err = handlers.getSrvHandler(methodName, v.MethodByName(methodName))
		if err == nil {
			ifWarnAnonymousFunc()
			handlers.addSrvHandler(msgName, msgHandler)
		}
	}

	handlers.addDefaultFunc(proc)
}

func (handlers *MsgHandler) addDefaultFunc(proc interface{}) {

	v := reflect.ValueOf(proc)
	var defaultFunc = v.MethodByName("MsgProc_DefaultMsgHandler")
	if defaultFunc.IsValid() {
		handlers.defaultFuncs = append(handlers.defaultFuncs, defaultFunc)
	}
}

// SetMainHander 设置父级消息路由器
func (handlers *MsgHandler) SetMainHander(msghandler iserver.IMsgHandler) {
	if msghandler != nil {
		handlers.mainHander = msghandler.(*MsgHandler)
		handlers.msgChan = msghandler.GetCallChan()
	}
}

// 获取有消息的信号量
func (handlers *MsgHandler) GetCallChan() chan bool {
	return handlers.msgChan
}

// // SetNoDelayMsgChan 设置不延迟的消息队列
// func (handlers *MsgHandler) SetNoDelayMsgChan(msgChan chan bool, msghandler iserver.IMsgHandlers) {
// 	handlers.msgChan = msgChan
// 	if msghandler != nil {
// 		handlers.mainHander = msghandler.(*MsgHandler)
// 	}
// }

// // 获取有消息的信号量
// func (handlers *MsgHandler) GetNoDelayCallChan() chan bool {
// 	return handlers.msgChan
// }

// FireMsg 触发消息, 保证不被挂起
func (handlers *MsgHandler) FireMsg(name string, content interface{}) {
	msg := &msgFireInfo{
		handler: handlers,
		name:    name,
		content: content,
	}
	handlers.fireMsg(msg)
	// if handlers.mainHander != nil {
	// 	handlers.mainHander.msgFireInfo.Put(msg)
	// } else {
	// 	handlers.msgFireInfo.Put(msg)
	// }
	select {
	case handlers.msgChan <- true:
	default:
	}
}

// 这里会牵扯到级联判断的问题，这样修改可以支持
func (handlers *MsgHandler) fireMsg(msg *msgFireInfo) {
	if handlers.mainHander != nil {
		handlers.mainHander.fireMsg(msg)
	} else {
		handlers.msgFireInfo.Put(msg)
	}
}

// FireRPC 触发消息, 保证不被挂起
func (handlers *MsgHandler) FireRPC(method string, data []byte) {
	msg := &rpcFireInfo{
		handler:    handlers,
		methodName: method,
		data:       data,
	}
	handlers.fireRPC(msg)
	// if handlers.mainHander != nil {
	// 	handlers.mainHander.rpcFireInfo.Put(msg)

	// } else {
	// 	handlers.rpcFireInfo.Put(msg)
	// }
	select {
	case handlers.msgChan <- true:
	default:
	}
}

// 这里会牵扯到级联判断的问题，这样修改可以支持
func (handlers *MsgHandler) fireRPC(msg *rpcFireInfo) {
	if handlers.mainHander != nil {
		handlers.mainHander.fireRPC(msg)
	} else {
		handlers.rpcFireInfo.Put(msg)
	}
}

// DoMsg 将缓冲的消息一次性处理
// 外部接口,需要在协程中调用
func (handlers *MsgHandler) DoMsg() {
	// if !handlers.enable {
	// 	return
	// }

	var procName string
	var info interface{}
	var err error
	var msgh *MsgHandler
	defer func() {
		if handlers.getRecover() {
			if err := recover(); err != nil {
				logger.Error(err, procName)
				buf := common.StackTrace()
				common.OnRecover(err, procName, buf, info)

				// common.UpPanic(common.NewPanicSrvMD(
				// 	int(iserver.GetSrvInst().GetGroupId()),
				// 	int(iserver.GetSrvInst().GetCurSrvInfo().ServerID),
				// 	"",
				// 	err,
				// 	buf,
				// ))
				if msgh != nil {
					msgh.OnPanicFunc(common.GetError(err))

				}
			}
		}
	}()
	// defer func() {
	// 	if handlers.getRecover() {
	// 		if err := recover(); err != nil {
	// 			logger.Error(err, procName)
	// 			buf := common.StackTrace()
	// 			common.UpPanic(common.NewPanicSrvMD(
	// 				int(iserver.GetSrvInst().GetGroupId()),
	// 				int(iserver.GetSrvInst().GetCurSrvInfo().ServerID),
	// 				"",
	// 				err,
	// 				buf,
	// 			))
	// 			if info != nil {
	// 				if msg, ok := info.(IFireInfo); ok {
	// 					if msg.GetHandler().GetOnPanicFunc() != nil {
	// 						msg.GetHandler().GetOnPanicFunc()(common.GetError(err))
	// 					}
	// 				}
	// 			}
	// 		}
	// 	}
	// }()

	for {
		info, err = handlers.msgFireInfo.Pop()
		if err != nil {
			break
		}

		msg := info.(*msgFireInfo)
		procName = msg.name
		msgh = msg.GetHandler()
		e := msg.handler.DoNormalMsg(msg.name, msg.content)
		// e := handlers.DoNormalMsg(msg.name, msg.content)
		if e != nil {
			logger.Error(e)
		}
	}

	for {
		info, err = handlers.rpcFireInfo.Pop()
		if err != nil {
			break
		}

		msg := info.(*rpcFireInfo)
		procName = msg.methodName
		msgh = msg.GetHandler()
		e := msg.handler.DoRPCMsg(msg.methodName, msg.data)
		if e != nil {
			if msg.methodName != "AutoFindPathReq" {
				logger.Error(e)
			}
		}
	}
}

func (handlers *MsgHandler) tryStartLogId(msgName string) {

}
func (handlers *MsgHandler) tryStopLogId() {

}

// DoRPCMsg RPC执行
func (handlers *MsgHandler) DoRPCMsg(methodName string, data []byte) error {
	handlers.tryStartLogId(methodName)
	defer handlers.tryStopLogId()

	ifuncs, ok := handlers.rpcFuncs.Load(methodName)
	if !ok {
		logger.Error("Method ", methodName, " Can't Find")
		return fmt.Errorf("Method %s can't find", methodName)
	}

	funcs, ok := ifuncs.([]reflect.Value)

	args := serializer.UnSerialize(data)
	callArgs := []reflect.Value{}
	for _, arg := range args {
		callArgs = append(callArgs, reflect.ValueOf(arg))
	}

	for _, rpcFunc := range funcs {
		outVal := rpcFunc.Call(callArgs)
		//如果有通用错误处理回调,则处理返回值 传递给通用错误处理
		if handlers.ProcessCommonErrorFunc != nil &&
			len(outVal) > 0 && outVal[0].CanInterface() {
			//parse IMsg
			var msg msgdef.IMsg
			if len(args) > 0 {
				if v, ok := args[0].(msgdef.IMsg); ok {
					msg = v
				}
			}
			//process with error
			if err, ok := outVal[0].Interface().(error); ok && err != nil {
				handlers.ProcessCommonErrorFunc(msg, err)
			} else if outVal[0].Interface() == nil {
				handlers.ProcessCommonErrorFunc(msg, nil)
			}
		}
	}

	return nil
}

func (handlers *MsgHandler) addMsgHandler(msgName string, msgHandler reflect.Value) {
	ifuncs, ok := handlers.msgFuncs.Load(msgName)

	var funcs []reflect.Value
	if !ok {
		funcs = make([]reflect.Value, 0, 10)
	} else {
		funcs = ifuncs.([]reflect.Value)

		for _, v := range funcs {
			if logger.CheckKey(logger.LogKey_RegMsgProc) &&
				v.Type().String() == msgHandler.Type().String() { // VALUE.Equal() cannot compare func(*msgdef.ClientVerifySucceedRet)
				logger.Warn("重复注册的消息(可能是正确的):", msgName, " ", msgHandler.Type().String(), " ", v.Type().String())
			}
		}
	}

	funcs = append(funcs, msgHandler)
	handlers.msgFuncs.Store(msgName, funcs)
}

func (handlers *MsgHandler) addRPCHandler(msgName string, msgHandler reflect.Value) {
	ifuncs, ok := handlers.rpcFuncs.Load(msgName)

	var funcs []reflect.Value
	if !ok {
		funcs = make([]reflect.Value, 0, 10)
	} else {
		funcs = ifuncs.([]reflect.Value)
		for _, v := range funcs {
			if logger.CheckKey(logger.LogKey_RegMsgProc) &&
				v.Type().String() == msgHandler.Type().String() {
				logger.Warn("重复注册的消息(可能是正确的):", msgName, " ", msgHandler.Type().String(), " ", v.Type().String())
			}
		}
	}

	funcs = append(funcs, msgHandler)
	handlers.rpcFuncs.Store(msgName, funcs)
}

// 返回true表示有重复的
func (handlers *MsgHandler) addSrvHandler(msgName string, msgHandler reflect.Value) bool {
	_, ok := handlers.srvFuncs.LoadOrStore(msgName, msgHandler)
	return ok
}

func (handlers *MsgHandler) getMsgHandler(methodName string, v reflect.Value) (string, reflect.Value, error) {
	if strings.HasPrefix(methodName, "MsgProc_") {
		return methodName[8:], v, nil
	}

	return "", reflect.ValueOf(nil), fmt.Errorf("")

	// methodHead := "MsgProc_"
	// methodHeadLen := len(methodHead)

	// if len(methodName) < methodHeadLen+1 {
	// 	return "", reflect.ValueOf(nil), fmt.Errorf("")
	// }

	// if methodName[0:methodHeadLen] != methodHead {
	// 	return "", reflect.ValueOf(nil), fmt.Errorf("")
	// }

	// msgName := methodName[methodHeadLen:]

	// //此处应该检查该函数是否是MsgHanderFunc类型的参数
	// return msgName, v, nil
}

// 获取服务器接口
func (handlers *MsgHandler) getSrvHandler(methodName string, v reflect.Value) (string, reflect.Value, error) {
	if strings.HasPrefix(methodName, "Srv_") {
		return methodName[4:], v, nil
	}

	return "", reflect.ValueOf(nil), fmt.Errorf("")
}

func (handlers *MsgHandler) getRPCHandler(methodName string, v reflect.Value) (string, reflect.Value, error) {
	if strings.HasPrefix(methodName, "RPC_") {
		return methodName[4:], v, nil
	}

	return "", reflect.ValueOf(nil), fmt.Errorf("")
}

// DoNormalMsg 立即触发消息
func (handlers *MsgHandler) DoNormalMsg(name string, content interface{}) error {
	handlers.tryStartLogId(name)
	defer handlers.tryStopLogId()

	if name == "RunHorseSrvReq" {
		logger.Info("发了跑马灯")
	}

	ifuncs, ok := handlers.msgFuncs.Load(name)
	if !ok {
		if len(handlers.defaultFuncs) == 0 {
			//如果是心跳，没有处理就没有处理，不做error输出
			if name == "HeartBeat" {
				return nil
			}
			return fmt.Errorf("Cant find handler %s", name)
		}

		for _, f := range handlers.defaultFuncs {
			if f.IsValid() {
				f.Call([]reflect.Value{reflect.ValueOf(name), reflect.ValueOf(content)})
			}
		}

		return nil
	}

	for _, msgFunc := range ifuncs.([]reflect.Value) {
		outVal := msgFunc.Call([]reflect.Value{reflect.ValueOf(content)})
		_ = outVal // 目前MsgHandler没有绑定会话,无法确定消息返回给谁,所以目前此处无法处理返回值.
	}

	return nil
}

func (handlers *MsgHandler) getRecover() bool {
	if srv := iserver.GetSrvInst(); srv == nil {
		return viper.GetBool("Config.Revover")
	} else {
		return srv.GetRecover()
	}
}
